package com.gitee.wsl.struct.combine

/**
 * A node in a [TModifier] chain. A CombinedModifier always contains at least two elements;
 * a Modifier [outer] that wraps around the Modifier [inner].
 */
abstract class BCombinedTModifier<E: BModifier.Element<E>>(
    internal val outer: E,
    internal val inner: E,
) : BModifier.Element<E> {

     override fun <R> foldIn(initial: R, operation: (R, E) -> R): R =
        inner.foldIn(outer.foldIn(initial, operation), operation)

     override fun <R> foldOut(initial: R, operation: (E, R) -> R): R =
        outer.foldOut(inner.foldOut(initial, operation), operation)

     override fun any(predicate: (E) -> Boolean): Boolean =
        outer.any(predicate) || inner.any(predicate)

     override fun all(predicate: (E) -> Boolean): Boolean =
        outer.all(predicate) && inner.all(predicate)

    //override fun then(other: E) = otherBlock(other)

    override fun equals(other: Any?): Boolean =
        other is BCombinedTModifier<*> && outer == other.outer && inner == other.inner

    override fun hashCode(): Int = outer.hashCode() + 31 * inner.hashCode()

    override fun toString() = "[" + foldIn("") { acc, element ->
        if (acc.isEmpty()) element.toString() else "$acc, $element"
    } + "]"
}